home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / DJLSR111.ZIP / libsrc / c / gen / fixpath.c < prev    next >
C/C++ Source or Header  |  1992-08-24  |  3KB  |  156 lines

  1. /*
  2.   (c) Copyright 1992 Eric Backus
  3.  
  4.   This software may be used freely so long as this copyright notice is
  5.   left intact.  There is no warrantee on this software.
  6. */
  7.  
  8. #include <dos.h>        /* For intdos() */
  9. #include <errno.h>        /* For errno */
  10. #include <string.h>        /* For strlen() */
  11.  
  12. int
  13. _get_default_drive(void)
  14. {
  15.     union REGS    regs;
  16.  
  17.     regs.h.ah = 0x19;        /* DOS Get Default Drive call */
  18.     regs.h.al = 0;
  19.     (void) intdos(®s, ®s);
  20.     return regs.h.al;
  21. }
  22.  
  23. static char *
  24. get_current_directory(char *out, int drive_number)
  25. {
  26.     union REGS    regs;
  27.  
  28.     regs.h.ah = 0x47;
  29.     regs.h.dl = drive_number + 1;
  30.     regs.x.si = (unsigned long) (out + 1);
  31.     (void) intdos(®s, ®s);
  32.     if (regs.x.cflag != 0)
  33.     {
  34.     errno = regs.x.ax;
  35.     return out;
  36.     }
  37.     else
  38.     {
  39.     /* Root path, don't insert "/", it'll be added later */
  40.     if (*(out + 1) != '\0')
  41.         *out = '/';
  42.     else
  43.         *out = '\0';
  44.     return out + strlen(out);
  45.     }
  46. }
  47.  
  48. static int
  49. is_slash(int c)
  50. {
  51.     return c == '/' || c == '\\';
  52. }
  53.  
  54. static int
  55. is_term(int c)
  56. {
  57.     return c == '/' || c == '\\' || c == '\0';
  58. }
  59.  
  60. /* Takes as input an arbitrary path.  Fixes up the path by:
  61.    1. Removing consecutive slashes
  62.    2. Removing trailing slashes
  63.    3. Making the path absolute if it wasn't already
  64.    4. Removing "." in the path
  65.    5. Removing ".." entries in the path (and the directory above them)
  66.    6. Adding a drive specification if one wasn't there
  67.    7. Converting all slashes to '/'
  68.  */
  69. void
  70. _fixpath(const char *in, char *out)
  71. {
  72.     int        drive_number;
  73.     const char    *ip = in;
  74.     char    *op = out;
  75.  
  76.     /* Add drive specification to output string */
  77.     if (*(ip + 1) == ':' && ((*ip >= 'a' && *ip <= 'z') ||
  78.                  (*ip >= 'A' && *ip <= 'Z')))
  79.     {
  80.     if (*ip >= 'a' && *ip <= 'z')
  81.         drive_number = *ip - 'a';
  82.     else
  83.         drive_number = *ip - 'A';
  84.     *op++ = *ip++;
  85.     *op++ = *ip++;
  86.     }
  87.     else
  88.     {
  89.     drive_number = _get_default_drive();
  90.     *op++ = drive_number + 'a';
  91.     *op++ = ':';
  92.     }
  93.  
  94.     /* Convert relative path to absolute */
  95.     if (!is_slash(*ip))
  96.     op = get_current_directory(op, drive_number);
  97.  
  98.     /* Step through the input path */
  99.     while (*ip)
  100.     {
  101.     /* Skip input slashes */
  102.     if (is_slash(*ip))
  103.     {
  104.         ip++;
  105.         continue;
  106.     }
  107.  
  108.     /* Skip "." and output nothing */
  109.     if (*ip == '.' && is_term(*(ip + 1)))
  110.     {
  111.         ip++;
  112.         continue;
  113.     }
  114.  
  115.     /* Skip ".." and remove previous output directory */
  116.     if (*ip == '.' && *(ip + 1) == '.' && is_term(*(ip + 2)))
  117.     {
  118.         ip += 2;
  119.         /* Don't back up over drive spec */
  120.         if (op > out + 2)
  121.         /* This requires "/" to follow drive spec */
  122.         while (!is_slash(*--op));
  123.         continue;
  124.     }
  125.  
  126.     /* Copy path component from in to out */
  127.     *op++ = '/';
  128.     while (!is_term(*ip)) *op++ = *ip++;
  129.     }
  130.  
  131.     /* If root directory, insert trailing slash */
  132.     if (op == out + 2) *op++ = '/';
  133.  
  134.     /* Null terminate the output */
  135.     *op = '\0';
  136. }
  137.  
  138. #ifdef    TEST
  139. #include <stdio.h>
  140.  
  141. int
  142. main(int argc, char **argv)
  143. {
  144.     char    path[90];
  145.     int        i;
  146.  
  147.     for (i = 1; i < argc; i++)
  148.     {
  149.     _fixpath(argv[i], path);
  150.     (void) printf("'%s' -> '%s'\n", argv[i], path);
  151.     }
  152.  
  153.     return 0;
  154. }
  155. #endif
  156.